﻿using System;
using System.Collections.Generic;

namespace MLog.Core.Appender {
    public abstract class BaseAppender<E> : IAppender<E> {
        private readonly List<Filter<E>> _filters = new List<Filter<E>>();


        public string Pattern { set; get; }
        public string Name { get; set; }

        public void DoAppend(E e) {
            for (var i = 0; i < _filters.Count; i++)
                if (_filters[i].Decide(e))
                    return;

            DoAppend0(e);
        }

        public void AddFilter(Filter<E> filter) {
            _filters.Add(filter);
        }

        public void ClearFilter() {
            _filters.Clear();
        }

        protected abstract void DoAppend0(E e);

        public virtual void ApplyConfig(Node config) {
            var child = config.Child;
            if (child != null)
                for (var i = 0; i < child.Count; i++) {
                    var n = child[i];
                    if (!CustomApply(n)) {
                        var info = LoggerConfiguration.GetPropertyName(GetType(), n);
//                        info.GetSetMethod().Invoke(this, new object[] {n.Value});
                        info.SetValue(this, n.Value, null);
                    }
                }
        }

        private void ApplyFilter(Node child) {
            var className = child.GetAttr("class");
            var type      = Type.GetType(className);
            var filter    = (BaseFilter<E>) Activator.CreateInstance(type);
            filter.ApplyConfig(child);
            AddFilter(filter);
        }

        protected virtual bool CustomApply(Node child) {
            if (Constants.FilterName.Equals(child.Name)) {
                ApplyFilter(child);
                return true;
            }

            return false;
        }

        public static BaseAppender<E> Create(Node config) {
            var className = config.GetAttr("class");
            var type      = Type.GetType(className);
            var appender  = (BaseAppender<E>) Activator.CreateInstance(type);
            appender.ApplyConfig(config);
            return appender;
        }
    }
}